package com.whxd.framework.security;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

import com.whxd.framework.spring.SpringContext;
import com.whxd.system.authority.entity.Authority;
import com.whxd.system.authority.repository.AuthorityDao;
import com.whxd.system.authority.web.AuthorityDto;
import com.whxd.system.resource.entity.Resource;

public class FrameworkInvocationSecurityMetadataSourceService implements
		FilterInvocationSecurityMetadataSource {

	// 使用注解方式的话，只能在构造函数执行完成后才能获得实例
	private EntityManagerFactory entityManagerFactory;

	private static Map<String, Collection<ConfigAttribute>> resourceMap = null;

	public FrameworkInvocationSecurityMetadataSourceService(EntityManagerFactory entityManagerFactory) {
		this.entityManagerFactory = entityManagerFactory;
		loadResourceDefine();
	}

	// 在Web服务器启动时，提取系统中的所有权限
	private void loadResourceDefine() {
		EntityManager em = entityManagerFactory.createEntityManager();
		Iterable<Authority> authorityList = em.createQuery("select a from Authority a").getResultList();
		/*
		 * 应当是资源为key， 权限为value。 资源通常为url， 权限就是那些以ROLE_为前缀的角色。 一个资源可以由多个权限来访问。
		 * sparta
		 */
		resourceMap = new HashMap<String, Collection<ConfigAttribute>>();

		for (Iterator<Authority> authorityIterator = authorityList.iterator(); authorityIterator
				.hasNext();) {
			Authority authority = authorityIterator.next();

			ConfigAttribute ca = new SecurityConfig(authority.getName());

			List<Resource> resourceList = authority.getResources();

			for (Resource resource : resourceList) {
				String url = resource.getString();
				/*
				 * 判断资源文件和权限的对应关系，如果已经存在相关的资源url，则要通过该url为key提取出权限集合，将权限增加到权限集合中。
				 * sparta
				 */
				if (resourceMap.containsKey(url)) {
					Collection<ConfigAttribute> value = resourceMap.get(url);
					value.add(ca);
					resourceMap.put(url, value);
				} else {
					Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
					atts.add(ca);
					resourceMap.put(url, atts);
				}
			}

		}
		
		ToStringBuilder.reflectionToString(resourceMap);
		em.close();
	}

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return null;
	}

	// 根据URL，找到相关的权限配置。
	@Override
	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException {

		// object 是一个URL，被用户请求的url。
		String url = ((FilterInvocation) object).getRequestUrl();
		System.out.println("url" + url);
		int firstQuestionMarkIndex = url.indexOf("?");

		if (firstQuestionMarkIndex != -1) {
			url = url.substring(0, firstQuestionMarkIndex);
		}

		Iterator<String> ite = resourceMap.keySet().iterator();

		while (ite.hasNext()) {
			String resURL = ite.next();

			if (url.equals(resURL)) {
				return resourceMap.get(resURL);
			}
		}

		return null;
	}

	@Override
	public boolean supports(Class<?> arg0) {

		return true;
	}

}